package cn.brilliantfuture.commentry.service;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.naming.NamingException;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.util.JSONUtils;

import org.jboss.resteasy.annotations.providers.jaxb.json.BadgerFish;

import cn.brilliantfuture.commentry.constants.OrderConstant;
import cn.brilliantfuture.commentry.entity.DataModels;
import cn.brilliantfuture.commentry.entity.Lockers;
import cn.brilliantfuture.commentry.entity.OrderInformation;
import cn.brilliantfuture.commentry.entity.OrderProductInfo;
import cn.brilliantfuture.commentry.entity.Purchaser;
import cn.brilliantfuture.commentry.entity.UserGroup;
import cn.brilliantfuture.commentry.exception.DuplicateSubmitException;
import cn.brilliantfuture.commentry.exception.InvokeFailureException;
import cn.brilliantfuture.commentry.exception.NullDataException;
import cn.brilliantfuture.commentry.exception.ParamErrorException;
import cn.brilliantfuture.commentry.lockers.DeliverStoreMessageLocal;
import cn.brilliantfuture.commentry.lockers.GoodsClubMessageLocal;
import cn.brilliantfuture.commentry.lockers.LockersAddressMessageLocal;
import cn.brilliantfuture.commentry.lockers.StorageServiceMessageLocal;
import cn.brilliantfuture.commentry.order.OrderMessageLocal;
import cn.brilliantfuture.commentry.user.UserMessageLocal;
import cn.brilliantfuture.commentry.util.CheckMatcher;
import cn.brilliantfuture.commentry.util.DateTimeHelper;
import cn.brilliantfuture.commentry.util.JDBCDataSource;

/**
 * 
 * Title: Communication Entry
 * 
 * Author: LiTian
 * 
 * Date: 2012-3-26
 * 
 * Description:
 * 
 */
@Path("/")
public class TransactionService extends AbstractTransactionService {

	public TransactionService() {
		init();
	}

	@POST
	@Path("member/login")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postMemberLogin(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("username") String username, @FormParam("password") String password) {
		logger.info("Member login request data is : username -> " + username + " password -> " + password);

		JSONObject result = new JSONObject();

		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			validAppParam(appKey, appCode);
			
			UserMessageLocal userMessageLocal = (UserMessageLocal) context.lookup("commentry-ear/UserMessageImpl/local");
		
			Object[] objs = userMessageLocal.memberLogin(username, password);

			if (null == objs) {
				throw new NullDataException();
			}

			result.accumulate("invoke_result", INVOKE_SUCCESS);

			JSONObject userInfo = new JSONObject();
			userInfo.accumulate("user_id", null != objs[1] ? objs[1].toString() : "");
			userInfo.accumulate("nick_name", null != objs[2] ? objs[2].toString() : "");
			userInfo.accumulate("phone", null != objs[3] ? objs[3].toString() : "");
			userInfo.accumulate("email", null != objs[4] ? objs[4].toString() : "");
			userInfo.accumulate("address", null != objs[5] ? objs[5].toString() : "");
			userInfo.accumulate("language", null != objs[6] ? objs[6].toString() : "");
			result.accumulate("user", userInfo);
			
		} catch (ParamErrorException e1) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} catch (NullDataException e) {
			result.accumulate("invoke_result", NULL_DATA);
		}

		logger.info("Return result -> " + result.toString());

		return result.toString();
	}

	@GET
	@Path("member/login")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getMemberLogin(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("username") String username, @QueryParam("password") String password) {
		return postMemberLogin(appKey, appCode, version, timestamp, format, username, password);
	}

	@POST
	@Path("delivery/addresses")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postAddresses(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("business_type") Integer businessType, @FormParam("data_format") Integer dataFormat, @FormParam("language") Integer language) {
		
		logger.info("businessType -> " + businessType + " dataFormat -> " + dataFormat + " language -> " + language);
		
		final int GENERAL_DATA_FORMAT = 1;
		final int SPREAD_DATA_FORMAT = 2;
		
		JSONObject result = new JSONObject();

		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			LockersAddressMessageLocal lockersAddressMessageLocal = (LockersAddressMessageLocal) context.lookup("commentry-ear/LockersAddressMessageImpl/local");
		
			List<Object[]> addressList = lockersAddressMessageLocal.getLockersAddresses(groupId, businessType);
			List<Object[]> dataModelList = lockersAddressMessageLocal.getDataModels();

			if (null != addressList && null != dataModelList) {
				
				if (null == dataFormat || dataFormat.intValue() == GENERAL_DATA_FORMAT){
					result.accumulate("invoke_result", INVOKE_SUCCESS);
					
					JSONArray addresses = new JSONArray();
					JSONArray dataModels = new JSONArray();
					
					for (Object[] objs : addressList) {
						JSONObject address = new JSONObject();
						address.accumulate("delivery_adress_key", (Integer) objs[0]);
						
						if (null == language || language.intValue() == 1) {
							address.accumulate("delivery_address_value", objs[1].toString() + objs[2].toString());
						} else if (language.intValue() == 3) {
							address.accumulate("delivery_address_value", objs[22].toString() + ", "+ objs[21].toString() + ", " + objs[20].toString() + ", " + objs[19].toString() + ", " + objs[18].toString() + ", " + objs[17].toString());
						}
						
						address.accumulate("latitude", objs[15]);
						address.accumulate("longitude", objs[16]);
	
						JSONArray storeModes = new JSONArray();
	
						if (null != objs[3] && Boolean.parseBoolean(objs[3].toString())) {
							JSONObject storeMode = new JSONObject();
							storeMode.accumulate("store_mode_key", 1);
							storeMode.accumulate("store_mode_value", "普通类型");
							storeModes.add(storeMode);
						}
	
						if (null != objs[4] && Boolean.parseBoolean(objs[4].toString())) {
							JSONObject storeMode = new JSONObject();
							storeMode.accumulate("store_mode_key", 2);
							storeMode.accumulate("store_mode_value", "保温类型");
							storeModes.add(storeMode);
						}
	
						if (null != objs[5] && Boolean.parseBoolean(objs[5].toString())) {
							JSONObject storeMode = new JSONObject();
							storeMode.accumulate("store_mode_key", 3);
							storeMode.accumulate("store_mode_value", "恒温类型");
							storeModes.add(storeMode);
						}
	
						address.accumulate("store_modes", storeModes);
						addresses.add(address);
					}
	
					for (Object[] objs : dataModelList) {
						JSONObject dataModel = new JSONObject();
						dataModel.accumulate("store_scope_key", (Integer) objs[0]);
						dataModel.accumulate("store_scope_value", objs[2].toString() + " - " + objs[3].toString());
						dataModels.add(dataModel);
					}
					
					result.accumulate("delivery_addresses", addresses);
					result.accumulate("store_scopes", dataModels);
				} else if (dataFormat.intValue() == SPREAD_DATA_FORMAT){
					result.accumulate("invoke_result", INVOKE_SUCCESS);

					JSONArray provinceInfos = new JSONArray();
					int currentProvineId = 0;
					int currentCityId = 0;
					int currentCountyId = 0;
					int currentVillageId = 0;
					
					int currentProvineIndex = -1;
					int currentCityIndex = -1;
					int currentCountyIndex = -1;
					int currentVillageIndex = -1;

					for (Object[] objs : addressList) {
						
						Integer provinceId = Integer.parseInt(objs[10].toString());
						String provinceName = null != language && language.intValue() == 3 ? objs[17].toString() : objs[11].toString();
						
						Integer cityId = Integer.parseInt(objs[8].toString());
						String cityName = null != language && language.intValue() == 3 ? objs[18].toString() : objs[9].toString();
						
						Integer countyId = Integer.parseInt(objs[6].toString());
						String countyName = null != language && language.intValue() == 3 ? objs[19].toString() : objs[7].toString();
						
						Integer villageId = Integer.parseInt(objs[12].toString());
						String villageName = null != language && language.intValue() == 3 ? objs[20].toString() : objs[13].toString();
						
						Integer lockersId = Integer.parseInt(objs[0].toString());
						String lockersName = null != language && language.intValue() == 3 ? objs[22].toString() : objs[2].toString();
						String locationName = null != language && language.intValue() == 3 ? objs[21].toString() : objs[14].toString();
						JSONObject lockersInfo = new JSONObject();
						lockersInfo.accumulate("lockersId", lockersId);
						lockersInfo.accumulate("lockersName", null != language && language.intValue() == 3 ? lockersName + ", " + locationName : locationName + lockersName);
						lockersInfo.accumulate("latitude", objs[15]);
						lockersInfo.accumulate("longitude", objs[16]);
						
						if (currentProvineId == 0 || currentProvineId != provinceId.intValue()){
							
							JSONObject provinceInfo = new JSONObject();
							provinceInfo.accumulate("provinceId", provinceId);
							provinceInfo.accumulate("provinceName", provinceName);
							
							JSONObject cityInfo = new JSONObject();
							cityInfo.accumulate("cityId", cityId);
							cityInfo.accumulate("cityName", cityName);
							
							JSONObject countyInfo = new JSONObject();
							countyInfo.accumulate("countyId", countyId);
							countyInfo.accumulate("countyName", countyName);
							
							JSONObject villageInfo = new JSONObject();
							villageInfo.accumulate("villageId", villageId);
							villageInfo.accumulate("villageName", villageName);
							
							JSONArray lockersInfos = new JSONArray();
							lockersInfos.add(lockersInfo);
							villageInfo.accumulate("lockers", lockersInfos);
							
							JSONArray villageInfos = new JSONArray();
							villageInfos.add(villageInfo);
							countyInfo.accumulate("villages", villageInfos);
							
							JSONArray countyInfos = new JSONArray();
							countyInfos.add(countyInfo);
							cityInfo.accumulate("counties", countyInfos);
							
							JSONArray cityInfos = new JSONArray();
							cityInfos.add(cityInfo);
							provinceInfo.accumulate("cities", cityInfos);
							
							provinceInfos.add(provinceInfo);
							
							currentProvineIndex++;
							currentCityIndex = 0;
							currentCountyIndex = 0;
							currentVillageIndex = 0;
						} else {
							JSONObject provinceInfo = provinceInfos.getJSONObject(currentProvineIndex);
							
							JSONArray cityInfos = provinceInfo.getJSONArray("cities");
							
							if (currentCityId == cityId.intValue()){
								JSONObject cityInfo = cityInfos.getJSONObject(currentCityIndex);
								
								JSONArray countyInfos = cityInfo.getJSONArray("counties");
								
								if (currentCountyId == countyId.intValue()){
									JSONObject countyInfo = countyInfos.getJSONObject(currentCountyIndex);
									
									JSONArray villageInfos = countyInfo.getJSONArray("villages");
									
									if (currentVillageId == villageId.intValue()){
										JSONObject villageInfo = villageInfos.getJSONObject(currentVillageIndex);
										
										JSONArray lockersInfos = villageInfo.getJSONArray("lockers");
										lockersInfos.add(lockersInfo);
										
										
									} else {
										JSONObject villageInfo = new JSONObject();
										villageInfo.accumulate("villageId", villageId);
										villageInfo.accumulate("villageName", villageName);
										
										JSONArray lockersInfos = new JSONArray();
										lockersInfos.add(lockersInfo);
										villageInfo.accumulate("lockers", lockersInfos);
										
										villageInfos.add(villageInfo);
										
										currentVillageIndex++;
									}
									
								} else {
									JSONObject countyInfo = new JSONObject();
									countyInfo.accumulate("countyId", countyId);
									countyInfo.accumulate("countyName", countyName);
									
									JSONObject villageInfo = new JSONObject();
									villageInfo.accumulate("villageId", villageId);
									villageInfo.accumulate("villageName", villageName);
									
									JSONArray lockersInfos = new JSONArray();
									lockersInfos.add(lockersInfo);
									villageInfo.accumulate("lockers", lockersInfos);
									
									JSONArray villiageInfos = new JSONArray();
									villiageInfos.add(villageInfo);
									countyInfo.accumulate("villages", villiageInfos);
									
									countyInfos.add(countyInfo);
									
									currentCountyIndex++;
									currentVillageIndex = 0;
								}
								
							} else {
								JSONObject cityInfo = new JSONObject();
								cityInfo.accumulate("cityId", cityId);
								cityInfo.accumulate("cityName", cityName);
								
								JSONObject countyInfo = new JSONObject();
								countyInfo.accumulate("countyId", countyId);
								countyInfo.accumulate("countyName", countyName);
								
								JSONObject villageInfo = new JSONObject();
								villageInfo.accumulate("villageId", villageId);
								villageInfo.accumulate("villageName", villageName);
								
								JSONArray lockersInfos = new JSONArray();
								lockersInfos.add(lockersInfo);
								villageInfo.accumulate("lockers", lockersInfos);
								
								JSONArray villiageInfos = new JSONArray();
								villiageInfos.add(villageInfo);
								countyInfo.accumulate("villages", villiageInfos);
								
								JSONArray countyInfos = new JSONArray();
								countyInfos.add(countyInfo);
								cityInfo.accumulate("counties", countyInfos);
								
								cityInfos.add(cityInfo);
								
								//provinceInfos.add(provinceInfo);
								
								currentCityIndex++;
								currentCountyIndex = 0;
								currentVillageIndex = 0;
							}
						}

						currentProvineId = provinceId.intValue();
						currentCityId = cityId.intValue();
						currentCountyId = countyId.intValue();
						currentVillageId = villageId.intValue();
					}

					result.accumulate("delivery_addresses", provinceInfos);
				} else {
					throw new ParamErrorException();
				}
			} else {
				result.accumulate("invoke_result", NULL_DATA);
			}
		} catch (ParamErrorException e1) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}

		logger.info("Return result -> " + result.toString());

		return result.toString();
	}

	@GET
	@Path("delivery/addresses")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getAddresses(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("business_type") Integer businessType, @QueryParam("data_format") Integer dataFormat, @QueryParam("language") Integer language) {
		return postAddresses(appKey, appCode, version, timestamp, format, businessType, dataFormat, language);
	}

	@POST
	@Path("online/payment")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postOnlinePayment(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("user_id") String userId, @FormParam("phone") String phone, @FormParam("order_code") String orderCode, @FormParam("amount") double amount, @FormParam("note") String note) {

		logger.info("Member online payment get request data is : user_id -> " + userId + " phone -> " + phone + " order_code -> " + orderCode + " amount -> " + amount + " note -> " + note);

		JSONObject result = new JSONObject();

		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			UserMessageLocal userMessageLocal = (UserMessageLocal) context.lookup("commentry-ear/UserMessageImpl/local");
			
			Object[] memberInfo = userMessageLocal.validMemberCode(userId);

			if (null != memberInfo) {
				if (userMessageLocal.isExistExpenseRecord(groupId.intValue() + orderCode)) {
					double balance = ((Double) memberInfo[memberInfo.length - 1]).doubleValue();
					if (balance >= amount) {
						String expenseCode = userMessageLocal.memberOnlinePayment((Integer) memberInfo[0], groupId, groupId.intValue() + orderCode, amount, note);
						if (null != expenseCode) {
							result.accumulate("invoke_result", PAYMENT_SUCCESS);
							result.accumulate("expense_code", expenseCode);
						} else {
							result.accumulate("invoke_result", PAYMENT_FAILURE);
						}
					} else {
						result.accumulate("invoke_result", SCANT_BALANCE);
					}

				} else {
					throw new DuplicateSubmitException();
				}
			} else {
				throw new ParamErrorException();
				
			}
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", PAYMENT_FAILURE);
		} catch (DuplicateSubmitException e) {
			result.accumulate("invoke_result", DUPLICATE_SUBMIT);
		}
		
		logger.info("Return result -> " + result.toString());
		
		return result.toString();

	}

	@GET
	@Path("online/payment")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getOnlinePayment(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("user_id") String userId, @QueryParam("phone") String phone, @QueryParam("order_code") String orderCode, @QueryParam("amount") double amount, @QueryParam("note") String note) {
		return postOnlinePayment(appKey, appCode, version, timestamp, format, userId, phone, orderCode, amount, note);
	}

	@POST
	@Path("order/transfer")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postOrderTransfer(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("order_info") String orderInfo) {

		logger.info("Order transfer request data is : order_info -> " + orderInfo);

		JSONObject result = new JSONObject();

		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			Date currentDate = new Date();

			orderInfo = orderInfo.replace("\r\n", "");

			JSONObject obj = JSONObject.fromObject(orderInfo);
			OrderInformation orderInformation = new OrderInformation();
			Lockers lockers = new Lockers();
			DataModels dataModels = new DataModels();
			Purchaser purchaser = new Purchaser();
			UserGroup group = new UserGroup();

			List<OrderProductInfo> orderProductInfos = new ArrayList<OrderProductInfo>();

			logger.info("Order message - > " + obj.toString());
			logger.info("Protocol version : " + obj.getDouble("version"));

			JSONObject memnerInfo = obj.getJSONObject("receiver_info");
			
			UserMessageLocal userMessageLocal = (UserMessageLocal) context.lookup("commentry-ear/UserMessageImpl/local");
		
			group.setGroupId(groupId);
			orderInformation.setGroup(group);

			String nickName = JSONUtils.isNull(memnerInfo.getString("nick_name")) ? "" : memnerInfo.getString("nick_name");
			String phone = JSONUtils.isNull(memnerInfo.getString("receiver_phone")) ? "" : memnerInfo.getString("receiver_phone");
			String email = JSONUtils.isNull(memnerInfo.getString("receiver_email")) ? "" : memnerInfo.getString("receiver_email");
			Integer language = memnerInfo.containsKey("language") ? JSONUtils.isNull(memnerInfo.get("language")) ? null : memnerInfo.getInt("language") : null;
			
			logger.info("NickName : " + nickName);
			logger.info("Phone : " + phone);
			logger.info("E-mail : " + email);
			
			if ((JSONUtils.isNull(phone) || "".equals(phone)) && (JSONUtils.isNull(email) || "".equals(email))){
				logger.error("Phone or emial not null!");
				throw new ParamErrorException();
			}

			// 验证手机号码及E-MAIL的合法性
			if (!JSONUtils.isNull(phone) && !"".equals(phone)){
				if (!CheckMatcher.check(phone, CheckMatcher.REGEX_HANDSET_NUMBER)) {
					logger.error("Check phone fail!");
					throw new ParamErrorException();
				}
			} else {
				phone = null;
			}
			
			if (!JSONUtils.isNull(email) && !"".equals(email)){
				if (!CheckMatcher.check(email, CheckMatcher.REGEX_EMAIL)){
					logger.error("Check email fail!");
					throw new ParamErrorException();
				}
			} else {
				email = null;
			}

			Object[] memberInfo = null;

			// 不同协议版本处理绿色家递会员信息
			if (obj.getDouble("version") == 1.0D) {
				memberInfo = userMessageLocal.validMemberCode(memnerInfo.getString("receiver_id"));
			} else if (obj.getDouble("version") == 1.2D) {
				memberInfo = userMessageLocal.validMemberInfo(phone, email);
				if (null == memberInfo) {
					memberInfo = userMessageLocal.createNewMemberInfo(nickName, email, phone, language);
				}
			} else {
				throw new NullDataException();
			}

			if (null == memberInfo) {
				throw new InvokeFailureException();
			}

			// 组织订单信息
			purchaser.setPurchaserId((Integer) memberInfo[0]);
			orderInformation.setPurchaser(purchaser);
			orderInformation.setReceiveName(nickName);
			orderInformation.setReceivePhone(phone);
			orderInformation.setRecevieEmail(email);

			orderInformation.setNumber(groupId.intValue() + obj.getString("order_code"));

			lockers.setLockersId(obj.getInt("delivery_address"));
			orderInformation.setLockers(lockers);

			orderInformation.setStoreMode(obj.getInt("store_mode"));

			if (obj.getInt("store_scope") != 0) {
				dataModels.setDataModelId(obj.getInt("store_scope"));
				orderInformation.setDataModels(dataModels);
			}

			orderInformation.setPaymentMode(obj.getInt("payment_mode"));
			orderInformation.setTotalAmount(obj.getDouble("order_total_price"));

			Date beginTime = DateTimeHelper.strToDateTime(obj.getString("store_begin_time"), DateTimeHelper.DEFAULT_DATE_TIME_FORMAT);
			Date endTime = DateTimeHelper.strToDateTime(obj.getString("store_end_time"), DateTimeHelper.DEFAULT_DATE_TIME_FORMAT);

			if (null != beginTime)
				orderInformation.setDeliveryTime(beginTime);

			if (null != endTime)
				orderInformation.setDeliveryEndTime(endTime);

			orderInformation.setOrderRemark(obj.getString("order_remark"));

			orderInformation.setInsertTime(currentDate);
			orderInformation.setEffective(true);
			orderInformation.setOrderSource(OrderConstant.ORDER_SOURCE_ONLINE_MALL);
			orderInformation.setTransactions(OrderConstant.WAIT_HANDLE);
			orderInformation.setOrderType(OrderConstant.DELIVERY_ORDER_TYPE);
			orderInformation.setDeleted(false);

			JSONArray productInfos = obj.getJSONArray("product_infos");

			// 获取商品信息
			for (int i = 0; i < productInfos.size(); i++) {
				JSONObject productInfo = productInfos.getJSONObject(i);

				OrderProductInfo orderProductInfo = new OrderProductInfo();
				orderProductInfo.setProductInfoId(productInfo.getInt("product_id"));
				orderProductInfo.setProductName(productInfo.getString("product_name"));
				orderProductInfo.setUnit(productInfo.getString("product_unit"));
				orderProductInfo.setPrice(productInfo.getDouble("price"));
				orderProductInfo.setAmount(productInfo.getInt("product_num"));
				orderProductInfo.setTotalPrice(productInfo.getDouble("total_price"));
				orderProductInfo.setInsertTime(currentDate);
				orderProductInfo.setDeleted(false);

				orderProductInfos.add(orderProductInfo);
			}
			
			OrderMessageLocal orderMessageLocal = (OrderMessageLocal) context.lookup("commentry-ear/OrderMessageImpl/local");
			
			// 确认是否为重复提交配送单
			if (!orderMessageLocal.isExistForOrder(orderInformation.getNumber())) {
				throw new DuplicateSubmitException();
			}

			// 保存配送单及商品信息
			if (orderMessageLocal.saveOrderInfo(orderInformation, orderProductInfos)) {
				result.accumulate("invoke_result", INVOKE_SUCCESS);
			} else {
				throw new InvokeFailureException();
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} catch (NullDataException e) {
			result.accumulate("invoke_result", NULL_DATA);
		} catch (InvokeFailureException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} catch (DuplicateSubmitException e) {
			result.accumulate("invoke_result", DUPLICATE_SUBMIT);
		}
		
		logger.info("Return result -> " + result.toString());
		
		return result.toString();
	}

	@GET
	@Path("order/transfer")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getOrderTransfer(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("order_info") String orderInfo) {
		return postOrderTransfer(appKey, appCode, version, timestamp, format, orderInfo);
	}

	@POST
	@Path("rfid/code")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postRfidCode(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("order_code") String orderCode) {

		logger.info("Rfid code request data is : order_code -> " + orderCode);

		JSONObject result = new JSONObject();

		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			OrderMessageLocal orderMessageLocal = (OrderMessageLocal) context.lookup("commentry-ear/OrderMessageImpl/local");
			
			orderCode = orderCode.replace("\r\n", "");

			JSONObject param = JSONObject.fromObject(orderCode);

			String rfidCode = orderMessageLocal.getRfidCode(groupId + param.getString("order_code"));

			if (null != rfidCode && !"".equals(rfidCode)) {
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("order_code", param.getString("order_code"));
				result.accumulate("rfid_code", rfidCode);
			} else {
				throw new InvokeFailureException();
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} catch (InvokeFailureException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}

		logger.info("Return result -> " + result.toString());

		return result.toString();
	}

	@GET
	@Path("rfid/code")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getRfidCode(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("order_code") String orderCode) {
		return postRfidCode(appKey, appCode, version, timestamp, format, orderCode);
	}
	
	@POST
	@Path("rfid/codes")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postRfidCodes(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("order_code") String orderCode, @FormParam("general_mode_num") Integer generalModeNum, @FormParam("keep_warm_mode_num") Integer keepWarmModeNum, @FormParam("thermostat_mode_num") Integer thermostatModeNum) {

		logger.info("Rfid code request data is : order_code -> " + orderCode);

		JSONObject result = new JSONObject();

		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			OrderMessageLocal orderMessageLocal = (OrderMessageLocal) context.lookup("commentry-ear/OrderMessageImpl/local");
			
			orderCode = orderCode.replace("\r\n", "");

			JSONArray[] results = orderMessageLocal.getRfidCodes(groupId + orderCode, generalModeNum, keepWarmModeNum, thermostatModeNum);

			if (null != results) {
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("order_code", orderCode);
				result.accumulate("general_codes", results[0]);
				result.accumulate("keep_warm_codes", results[1]);
				result.accumulate("thermostat_codes", results[2]);
			} else {
				throw new InvokeFailureException();
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} catch (InvokeFailureException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}

		logger.info("Return result -> " + result.toString());

		return result.toString();
	}

	@GET
	@Path("rfid/codes")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getRfidCodes(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("order_code") String orderCode, @QueryParam("general_mode_num") Integer generalModeNum, @QueryParam("keep_warm_mode_num") Integer keepWarmModeNum, @QueryParam("thermostat_mode_num") Integer thermostatModeNum) {
		return postRfidCodes(appKey, appCode, version, timestamp, format, orderCode, generalModeNum, keepWarmModeNum, thermostatModeNum);
	}

	@POST
	@Path("online/refund")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postOnlineRefund(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("expense_code") String expenseCode, @FormParam("user_id") String userId, @FormParam("phone") String phone, @FormParam("order_code") String orderCode, @FormParam("amount") double amount, @FormParam("note") String note) {
		logger.info("Member online refund get request data is : expense_code -> " + expenseCode + " user_id -> " + userId + " phone -> " + phone + " order_code -> " + orderCode + " amount -> " + amount + " note -> " + note);

		JSONObject result = new JSONObject();

		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			UserMessageLocal userMessageLocal = (UserMessageLocal) context.lookup("commentry-ear/UserMessageImpl/local");
			
			Object[] memberInfo = userMessageLocal.validMemberCode(userId);

			if (memberInfo[2].toString().equals(phone) && userMessageLocal.memberOnlineRefund(expenseCode, (Integer) memberInfo[0], groupId, groupId + orderCode, amount, note)) {
				result.accumulate("invoke_result", REFUND_SUCCESS);
				logger.info("Return result -> " + result.toString());
			} else {
				throw new InvokeFailureException();
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", REFUND_FAILURE);
		} catch (InvokeFailureException e) {
			result.accumulate("invoke_result", REFUND_FAILURE);
		}
		
		logger.info("Return result -> " + result.toString());
		return result.toString();
	}

	@GET
	@Path("online/refund")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getOnlineRefund(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("expense_code") String expenseCode, @QueryParam("user_id") String userId, @QueryParam("phone") String phone, @QueryParam("order_code") String orderCode, @QueryParam("amount") double amount, @QueryParam("note") String note) {
		return postOnlineRefund(appKey, appCode, version, timestamp, format, expenseCode, userId, phone, orderCode, amount, note);
	}

	@POST
	@Path("synch/order/state")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postSynchOrderState(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("order_code") String orderCode, @FormParam("synch_mode") String synchMode) {

		logger.info("Synch order state get request data is :  order_code -> " + orderCode + " synch_mode -> " + synchMode);

		String QUERY_ORDER_STATE = "QUERY_ORDER_STATE";
		String REFUND_ORDER_CODE = "REFUND_ORDER_CODE";

		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			OrderMessageLocal orderMessageLocal = (OrderMessageLocal) context.lookup("commentry-ear/OrderMessageImpl/local");
		
			if (QUERY_ORDER_STATE.equals(synchMode)) {
				Integer orderState = orderMessageLocal.queryOrderState(groupId + orderCode);
				if (null != orderState) {
					result.accumulate("invoke_result", INVOKE_SUCCESS);
					result.accumulate("synch_result", orderState + "");
				} else {
					throw new InvokeFailureException();
				}
			} else if (REFUND_ORDER_CODE.equals(synchMode)) {
				if (orderMessageLocal.modfiyRefundOrderState(groupId + orderCode)) {
					result.accumulate("invoke_result", INVOKE_SUCCESS);
					result.accumulate("synch_result", "");
				} else {
					throw new InvokeFailureException();
				}
			}
		
		} catch (ParamErrorException e1) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} catch (InvokeFailureException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}
		
		logger.info("Return result -> " + result.toString());

		return result.toString();
	}

	@GET
	@Path("synch/order/state")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getSynchOrderState(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("order_code") String orderCode, @QueryParam("synch_mode") String synchMode) {
		return postSynchOrderState(appKey, appCode, version, timestamp, format, orderCode, synchMode);
	}
	
	@POST
	@Path("member/balance")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postMemberBalance(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("user_id") String userId, @FormParam("phone") String phone) {
		logger.info("Member login request data is : userId -> " + userId + " phone -> " + phone);
		
		JSONObject result = new JSONObject();

		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			UserMessageLocal userMessageLocal = (UserMessageLocal) context.lookup("commentry-ear/UserMessageImpl/local");
			
			Double balance = userMessageLocal.queryMemberBalance(userId, phone);
			
			if (null != balance){
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("account_balance", balance.doubleValue());
			} else {
				result.accumulate("invoke_result", INVOKE_FAILURE);
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}

		logger.info("Return result -> " + result.toString());
		
		return result.toString();
	}
	
	@GET
	@Path("member/balance")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getMemberBalance(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("user_id") String userId, @QueryParam("phone") String phone) {
		return postMemberBalance(appKey, appCode, version, timestamp, format, userId, phone);
	}
	
	@POST
	@Path("storage/business")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postStorageBusiness(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("business_type") String businessType, @FormParam("business_param") String businessParam){
		logger.info("Storage business : businessType -> " + businessType + " businessParam -> " + businessParam);
		
		String CREATE_STORAGE_CODE = "CREATE_STORAGE_CODE";
		String QUERY_STORAGE_INFO = "QUERY_STORAGE_INFO";
		
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			JSONObject param = JSONObject.fromObject(businessParam);
			
			String phone = param.getString("user_phone");
			Integer language = param.containsKey("language") ? JSONUtils.isNull(param.get("language")) ? null : param.getInt("language") : null;
			
			
			if (!CheckMatcher.check(phone, CheckMatcher.REGEX_HANDSET_NUMBER)) {
				throw new ParamErrorException();
			}
			
			UserMessageLocal userMessageLocal = (UserMessageLocal) context.lookup("commentry-ear/UserMessageImpl/local");
			
			Object[] objs = userMessageLocal.validMemberInfo(phone, null);
			
			if (null == objs){
				objs = userMessageLocal.createNewMemberInfo("", "", phone, language);
			}
			
			if (CREATE_STORAGE_CODE.equals(businessType)){

				String orderCode = param.getString("order_code");
				int lockersId = param.getInt("lockers_id");

				StorageServiceMessageLocal storageServiceMessageLocal = (StorageServiceMessageLocal) context.lookup("commentry-ear/StorageServiceMessageImpl/local");
				
				String storageCode = storageServiceMessageLocal.createStorageServiceInfo(Integer.parseInt(objs[0].toString()), orderCode, groupId, lockersId);
				
				if (null == storageCode){
					throw new InvokeFailureException();
				}
				
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("storage_code", storageCode);
				
			} else if (QUERY_STORAGE_INFO.equals(businessType)){
				StorageServiceMessageLocal storageServiceMessageLocal = (StorageServiceMessageLocal) context.lookup("commentry-ear/StorageServiceMessageImpl/local");
				
				String obj = storageServiceMessageLocal.queryStorageServiceInfo(Integer.parseInt(objs[0].toString()), groupId);
				
				if (null == obj){
					throw new InvokeFailureException();
				}
				
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("storage_infos", JSONArray.fromObject(obj));
				
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} catch (InvokeFailureException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}

		logger.info("Return result -> " + result.toString());
		
		return result.toString();
	}
	
	@GET
	@Path("storage/business")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getStorageBusiness(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("business_type") String businessType, @QueryParam("business_param") String businessParam){
		return postStorageBusiness(appKey, appCode, version, timestamp, format, businessType, businessParam);
	}
	
	@POST
	@Path("goodsclub/business")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postGoodsClubBusiness(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("business_type") String businessType, @FormParam("business_param") String businessParam){
		logger.info("Storage business : businessType -> " + businessType + " businessParam -> " + businessParam);
		
		String CREATE_STORAGE_CODE = "CREATE_STORAGE_CODE";
		String CREATE_STORAGE_KEY = "CREATE_STORAGE_KEY";
		String QUERY_STORAGE_INFO = "QUERY_STORAGE_INFO";
		String QUERY_STORAGE_KEY = "QUERY_STORAGE_KEY";
		
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			JSONObject param = JSONObject.fromObject(businessParam);
			
			String phone = param.getString("user_phone");
			Integer language = param.containsKey("language") ? JSONUtils.isNull(param.get("language")) ? null : param.getInt("language") : null;
			
			if (!CheckMatcher.check(phone, CheckMatcher.REGEX_HANDSET_NUMBER)) {
				throw new ParamErrorException();
			}
			
			UserMessageLocal userMessageLocal = (UserMessageLocal) context.lookup("commentry-ear/UserMessageImpl/local");
			
			Object[] objs = userMessageLocal.validMemberInfo(phone, null);
			
			if (null == objs){
				objs = userMessageLocal.createNewMemberInfo("", "", phone, language);
			}
			
			if (CREATE_STORAGE_CODE.equals(businessType)){

				String orderCode = param.getString("order_code");
				int lockersId = param.getInt("lockers_id");

				GoodsClubMessageLocal goodsClubMessageLocal = (GoodsClubMessageLocal) context.lookup("commentry-ear/GoodsClubMessageImpl/local");
				
				String storageCode = goodsClubMessageLocal.createStorageRfid(Integer.parseInt(objs[0].toString()), orderCode, groupId, lockersId);
				
				if (null == storageCode){
					throw new InvokeFailureException();
				}
				
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("storage_code", storageCode);
				
			} else if (CREATE_STORAGE_KEY.equals(businessType)) {
				String orderCode = param.getString("order_code");
				int lockersId = param.getInt("lockers_id");

				GoodsClubMessageLocal goodsClubMessageLocal = (GoodsClubMessageLocal) context.lookup("commentry-ear/GoodsClubMessageImpl/local");

				if (goodsClubMessageLocal.createStorageKey(Integer.parseInt(objs[0].toString()), orderCode, groupId, lockersId)){
					result.accumulate("invoke_result", INVOKE_SUCCESS);
				} else {
					throw new InvokeFailureException();
				}

			}else if (QUERY_STORAGE_INFO.equals(businessType)){
				String startTime = param.getString("start_time");
				String endTime = param.getString("end_time");
				
				GoodsClubMessageLocal goodsClubMessageLocal = (GoodsClubMessageLocal) context.lookup("commentry-ear/GoodsClubMessageImpl/local");
				
				JSONArray obj = goodsClubMessageLocal.queryStorageServiceInfo(Integer.parseInt(objs[0].toString()), groupId, startTime, endTime);
				
				if (null == obj){
					throw new InvokeFailureException();
				}
				
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("storage_infos", obj);
				
			} else if (QUERY_STORAGE_KEY.equals(businessType)) {
				String startTime = param.getString("start_time");
				String endTime = param.getString("end_time");
				
				GoodsClubMessageLocal goodsClubMessageLocal = (GoodsClubMessageLocal) context.lookup("commentry-ear/GoodsClubMessageImpl/local");
				
				JSONArray obj = goodsClubMessageLocal.queryStorageServiceKey(Integer.parseInt(objs[0].toString()), groupId, startTime, endTime);
				
				if (null == obj){
					throw new InvokeFailureException();
				}
				
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("storage_infos", obj);
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} catch (InvokeFailureException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}

		logger.info("Return result -> " + result.toString());
		
		return result.toString();
	}
	
	@GET
	@Path("goodsclub/business")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getGoodsClubBusiness(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("business_type") String businessType, @QueryParam("business_param") String businessParam){
		return postGoodsClubBusiness(appKey, appCode, version, timestamp, format, businessType, businessParam);
	}
	
	@POST
	@Path("store/points")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postStorePoints(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format){
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			validAppParam(appKey, appCode);
			
			LockersAddressMessageLocal lockersAddressMessageLocal = (LockersAddressMessageLocal) context.lookup("commentry-ear/LockersAddressMessageImpl/local");
			
			JSONArray obj = lockersAddressMessageLocal.getStorePoints();
			
			if (null == obj){
				throw new InvokeFailureException();
			}
			
			result.accumulate("invoke_result", INVOKE_SUCCESS);
			result.accumulate("store_points", obj);
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} catch (InvokeFailureException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}
		
		return result.toString();
	}
	
	@GET
	@Path("store/points")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getStorePoints(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format){
		return postStorePoints(appKey, appCode, version, timestamp, format);
	}
		
	@POST
	@Path("goods/details")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postGoodsDetails(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("device_sn") String deviceSn){
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			validAppParam(appKey, appCode);
			
			Connection conn = null;
			PreparedStatement pstm = null;
			ResultSet rs = null;

			try {
				conn = JDBCDataSource.getConnection();
				pstm = conn.prepareStatement("select sg.storage_grid_id, sg.grid_num, max(sgpn.storage_grid_purchaser_news_id) as sgpn_id from storage_grid sg left join lockers l on l.lockers_id = sg.lockers_id left join storage_grid_purchaser_news sgpn on sg.storage_grid_id = sgpn.storage_grid_id where sg.deleted = 0 and l.deleted = 0 and l.device_sn = '" + deviceSn + "' group by sg.storage_grid_id order by sg.grid_num");
				rs = pstm.executeQuery();
				
				JSONArray datas = new JSONArray();
				
				StringBuffer sb = new StringBuffer();
				while (rs.next()) {
					JSONObject data = new JSONObject();
					data.accumulate("storage_grid_id", rs.getInt("storage_grid_id"));
					data.accumulate("grid_num", rs.getInt("grid_num"));
					data.accumulate("has_goods", false);
					data.accumulate("passwd", "");
					datas.add(data);
					
					if (null != rs.getObject("sgpn_id")){
						sb.append(rs.getInt("sgpn_id")).append(",");
					}
				}
				
				rs = null;
				pstm = null;
				
				if (!"".equals(sb.toString())){
					pstm = conn.prepareStatement("select sgpn.storage_grid_id, sgpn.closing, pb.passwd from storage_grid_purchaser_news sgpn inner join product_batch pb on sgpn.rfid_sn = pb.rfid_sn where sgpn.storage_grid_purchaser_news_id in (" + sb.toString().substring(0, sb.toString().length() - 1) + ") group by sgpn.storage_grid_id");
					rs = pstm.executeQuery();
					
					Map<Integer, Object[]> map = new HashMap<Integer, Object[]>();
					
					while (rs.next()) {
						Object[] obj = new Object[2];
						obj[0] = rs.getObject("closing");
						obj[1] = rs.getObject("passwd");
						
						if (rs.getInt("closing") == 0){
							obj[0] = true;
							obj[1] = rs.getString("passwd");
						} else {
							obj[0] = false;
							obj[1] = "";
						}
						
						map.put(rs.getInt("storage_grid_id"), obj);
						
					}
					
					for (int i = 0; i < datas.size(); i++) {
						JSONObject data = datas.getJSONObject(i);
						
						if (map.containsKey(data.getInt("storage_grid_id"))){
							Object[] obj = map.get(data.getInt("storage_grid_id"));
							data.element("has_goods", obj[0]);
							data.element("passwd", obj[1]);
						} else {
							data.element("has_goods", false);
							data.element("passwd", "");
						}
					}
				}

				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("prize_list", datas);
				
			} catch (Exception e) {
				logger.error("Get goods details fail!", e);
				result.accumulate("invoke_result", INVOKE_FAILURE);
			} finally {
				JDBCDataSource.closeResource(conn, pstm, rs);
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}
		
		logger.info(result.toString());

		return result.toString();
	}
	
	@GET
	@Path("goods/details")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getGoodsDetails(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("device_sn") String deviceSn){
		return postGoodsDetails(appKey, appCode, version, timestamp, format, deviceSn);
	}
	
	@POST
	@Path("store/service")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postStoreService(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("business_type") String businessType, @FormParam("business_param") String businessParam){
		logger.info("Storage business : businessType -> " + businessType + " businessParam -> " + businessParam);
		
		String CREATE_STORAGE_CODE = "CREATE_STORAGE_CODE";
		String CREATE_STORAGE_KEY = "CREATE_STORAGE_KEY";
		String REMOVE_STORAGE_KEY = "REMOVE_STORAGE_KEY";
		//String QUERY_STORAGE_INFO = "QUERY_STORAGE_INFO";
		//String QUERY_STORAGE_KEY = "QUERY_STORAGE_KEY";
		
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			Integer groupId = validAppParam(appKey, appCode);
			
			JSONObject param = JSONObject.fromObject(businessParam);
			
			String phone = param.getString("user_phone");
			Integer language = param.containsKey("language") ? JSONUtils.isNull(param.get("language")) ? null : param.getInt("language") : null;
			
			if (!CheckMatcher.check(phone, CheckMatcher.REGEX_HANDSET_NUMBER)) {
				throw new ParamErrorException();
			}
			
			UserMessageLocal userMessageLocal = (UserMessageLocal) context.lookup("commentry-ear/UserMessageImpl/local");
			
			Object[] objs = userMessageLocal.validMemberInfo(phone, null);
			
			if (null == objs){
				objs = userMessageLocal.createNewMemberInfo("", "", phone, language);
			}
			
			/*if (CREATE_STORAGE_CODE.equals(businessType)){

				String orderCode = DateTimeHelper.dateTimeToStr(new Date(), DateTimeHelper.DEFAULT_DATE_TIME_NOT_SPACE_FORMAT);
				int lockersId = param.getInt("lockers_id");

				DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");
				
				JSONObject storageCode = deliverStoreMessageLocal.createStorageRfid(Integer.parseInt(objs[0].toString()), orderCode, groupId, lockersId);
				
				if (null == storageCode){
					throw new InvokeFailureException();
				}
				
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("storage_code", storageCode.getString("storage_code"));
				result.accumulate("storage_passwd", storageCode.getString("storage_passwd"));
				result.accumulate("lockers_name", storageCode.getString("lockers_name"));
				
			} else if (CREATE_STORAGE_KEY.equals(businessType)) {
				String orderCode = DateTimeHelper.dateTimeToStr(new Date(), DateTimeHelper.DEFAULT_DATE_TIME_NOT_SPACE_FORMAT);
				int lockersId = param.getInt("lockers_id");

				DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");
				
				JSONObject storageKey = deliverStoreMessageLocal.createStorageKey(Integer.parseInt(objs[0].toString()), orderCode, groupId, lockersId);
				
				if (null != storageKey){
					result.accumulate("invoke_result", INVOKE_SUCCESS);
					result.accumulate("storage_key", storageKey.getInt("storage_key"));
					result.accumulate("lockers_name", storageKey.getString("lockers_name"));
				} else {
					throw new InvokeFailureException();
				}

			} else if (REMOVE_STORAGE_KEY.equals(businessType)) {
				DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");
				
				int lockersId = param.getInt("lockers_id");
				
				if (deliverStoreMessageLocal.removeStorageKey(Integer.parseInt(objs[0].toString()), groupId, lockersId)){
					result.accumulate("invoke_result", INVOKE_SUCCESS);
				} else {
					throw new InvokeFailureException();
				}
			} else if (QUERY_STORAGE_INFO.equals(businessType)){
				String startTime = param.getString("start_time");
				String endTime = param.getString("end_time");
				
				DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");
				
				JSONArray obj = goodsClubMessageLocal.queryStorageServiceInfo(Integer.parseInt(objs[0].toString()), groupId, startTime, endTime);
				
				if (null == obj){
					throw new InvokeFailureException();
				}
				
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("storage_infos", obj);
				
			} else if (QUERY_STORAGE_KEY.equals(businessType)) {
				String startTime = param.getString("start_time");
				String endTime = param.getString("end_time");
				
				DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");
				
				JSONArray obj = goodsClubMessageLocal.queryStorageServiceKey(Integer.parseInt(objs[0].toString()), groupId, startTime, endTime);
				
				if (null == obj){
					throw new InvokeFailureException();
				}
				
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("storage_infos", obj);
			}*/
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		} 

		logger.info("Return result -> " + result.toString());
		
		return result.toString();
	}
	
	@GET
	@Path("store/service")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getStoreService(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("business_type") String businessType, @QueryParam("business_param") String businessParam){
		return postStoreService(appKey, appCode, version, timestamp, format, businessType, businessParam);
	}
	
	@POST
	@Path("store/reserve")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postStoreReserve(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("phone") String phone, @FormParam("lockers_id") Integer lockersId, @FormParam("service_type") Integer serviceType, @FormParam("store_type") Integer storeType, @FormParam("grid_type") Integer gridType, @FormParam("begin_time") Long beginTime, @FormParam("end_time") Long endTime, @FormParam("language") Integer language){
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			int groupId = validAppParam(appKey, appCode);

			if (!CheckMatcher.check(phone, CheckMatcher.REGEX_HANDSET_NUMBER)) {
				throw new ParamErrorException();
			}
			
			UserMessageLocal userMessageLocal = (UserMessageLocal) context.lookup("commentry-ear/UserMessageImpl/local");
			
			Object[] objs = userMessageLocal.validMemberInfo(phone, null);
			
			if (null == objs){
				objs = userMessageLocal.createNewMemberInfo("", "", phone, language);
			}

			DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");
			JSONObject storeInfo = deliverStoreMessageLocal.createStoreReserve((Integer)objs[0], groupId, lockersId, 1, storeType, gridType, beginTime, endTime);
			if (null != storeInfo){
				result.accumulate("invoke_result", INVOKE_SUCCESS);
				result.accumulate("store_code", storeInfo.getString("store_code"));
				result.accumulate("store_passwd", storeInfo.getString("store_passwd"));
				result.accumulate("area", storeInfo.getString("area"));
				result.accumulate("address", storeInfo.getString("address"));
				
			} else {
				result.accumulate("invoke_result", INVOKE_FAILURE);
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}
		
		logger.info(result.toString());
		
		return result.toString();
	}
	
	@GET
	@Path("store/reserve")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getStoreReserve(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("phone") String phone, @QueryParam("lockers_id") Integer lockersId, @QueryParam("service_type") Integer serviceType, @QueryParam("store_type") Integer storeType, @QueryParam("grid_type") Integer gridType, @QueryParam("begin_time") Long beginTime, @QueryParam("end_time") Long endTime, @QueryParam("language") Integer language){
		return postStoreReserve(appKey, appCode, version, timestamp, format, phone, lockersId, serviceType, storeType, gridType, beginTime, endTime, language);
	}
	
	@POST
	@Path("store/unreserve")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postStoreUnreserve(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("store_code") String storeCode){
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			validAppParam(appKey, appCode);

			DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");

			if (deliverStoreMessageLocal.createStoreUnreserve(storeCode)){
				result.accumulate("invoke_result", INVOKE_SUCCESS);
			} else {
				result.accumulate("invoke_result", INVOKE_FAILURE);
			}
			
		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}
		
		logger.info(result.toString());
		
		return result.toString();
	}
	
	@GET
	@Path("store/unreserve")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getStoreUnreserve(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("store_code") String storeCode){
		return postStoreUnreserve(appKey, appCode, version, timestamp, format, storeCode);
	}
	
	@POST
	@Path("lockers/list")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postLockersList(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format){
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			validAppParam(appKey, appCode);
			
			result.accumulate("invoke_result", INVOKE_SUCCESS);

			DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");
			
			result.accumulate("location_infos", deliverStoreMessageLocal.getStorePointList());

		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}
		
		logger.info(result.toString());
		
		return result.toString();
	}
	
	@GET
	@Path("lockers/list")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getLockersList(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format){
		return postLockersList(appKey, appCode, version, timestamp, format);
	}
	
	@POST
	@Path("lockers/grid/config")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postLockersGridConfig(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("lockers_id") Integer lockersId){
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			validAppParam(appKey, appCode);
			
			result.accumulate("invoke_result", INVOKE_SUCCESS);

			DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");
			
			result.accumulate("lockers_config", deliverStoreMessageLocal.getStoreGridConfig(lockersId));

		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}
		
		logger.info(result.toString());
		
		return result.toString();
	}
	
	@GET
	@Path("lockers/grid/config")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getLockersGridConfig(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("lockers_id") Integer lockersId){
		return postLockersGridConfig(appKey, appCode, version, timestamp, format, lockersId);
	}

	@POST
	@Path("store/status")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String postStoreStatus(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @FormParam("store_code") String storeCode){
		JSONObject result = new JSONObject();
		
		try {
			validParam(appKey, appCode, version, timestamp, format);
			
			validAppParam(appKey, appCode);
			
			result.accumulate("invoke_result", INVOKE_SUCCESS);

			DeliverStoreMessageLocal deliverStoreMessageLocal = (DeliverStoreMessageLocal) context.lookup("commentry-ear/DeliverStoreMessageImpl/local");
			
			result.accumulate("store_status", deliverStoreMessageLocal.getStoreInfo(storeCode));

		} catch (ParamErrorException e) {
			result.accumulate("invoke_result", PARAM_ERROR);
		} catch (NamingException e) {
			result.accumulate("invoke_result", INVOKE_FAILURE);
		}
		
		logger.info(result.toString());
		
		return result.toString();
	}
	
	@GET
	@Path("store/status")
	@Produces( { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
	@BadgerFish
	public String getStoreStatus(@QueryParam("app_key") String appKey, @QueryParam("app_code") String appCode, @QueryParam("v") String version, @QueryParam("timestamp") String timestamp, @QueryParam("format") String format, @QueryParam("store_code") String storeCode){
		return postStoreStatus(appKey, appCode, version, timestamp, format, storeCode);
	}
}
